Greenness Exposure Assessment in Environmental Health Research

Amman, July 5th 2025

Leire Luque García

University of California San Diego

EXERCISE 1: Mitigation pathway

In this exercise, we explore how different greenness metrics influence health through the mitigation pathway. As has already been noted, the mitigation pathway influences human health by reducing environmental stressors, including air pollution, heat, and noise, through the presence of surrounding vegetation.

DESCRIPTION

We conducted a prospective study involving 6,243 adult participants monitored during the warm season (May to September), to investigate the potential influence of mean daytime temperature on heart rate, and whether this association is modified by surrounding vegetation. Each participant was equipped with a validated wearable device capable of continuously recording daytime heart rates. NDVI and tree cover (%) were estimated at the residential level using remote sensing data aggregated within a 500-meter buffer surrounding each participant’s home address. In this analysis, NDVI and tree cover are treated as potential effect modifiers of the association between ambient daytime temperature and physiological stress, as reflected by heart rate.

install.packages("readr")
install.packages("dplyr")
install.packages("data.table")
install.packages("ggplot2")
install.packages("skimr")
install.packages("patchwork")
install.packages("broom")
install.packages("ggeffects")

We will start installing the required packages.

library(readr)
Mitigation <- read_csv("Mitigation.csv")

Next, load the synthetic dataset titled “Mitigation.csv”.

str(Mitigation)

Examine the structure of the dataset. The “Mitigation” dataset simulates data for 6,243 adult participants with the following variables:

Mitigation$sex <- factor(Mitigation$sex, labels = c("Female", "Male"))
Mitigation$ses <- factor(Mitigation$ses, labels = c("I", "II", "III", "IV", "V"))

Recode categorical variables in the “Mitigation” dataset as factor.

library(skimr)

Obtain descriptive statistics for the exposure and outcome variables in the “Mitigation” dataset using “skimr”.

skim(Mitigation[, c("mean_temp", "ndvi", "tree_cover", "mean_hr")])

Check the distribution of the exposure and outcome variables.


Mitigation$ndvi_tertile <- cut(Mitigation$ndvi,
                           breaks = quantile(Mitigation$ndvi, probs = c(0, 1/3, 2/3, 1), na.rm = TRUE),
                           include.lowest = TRUE,
                           labels = c("Low", "Medium", "High"))

Mitigation$tc_tertile <- cut(Mitigation$tree_cover,
                         breaks = quantile(Mitigation$tree_cover, probs = c(0, 1/3, 2/3, 1), na.rm = TRUE),
                         include.lowest = TRUE,
                         labels = c("Low", "Medium", "High"))

Create tertiles for NDVI and tree cover.

Mitigation$ndvi_tertile <- factor(Mitigation$ndvi_tertile, levels = c("Low", "Medium", "High"))
Mitigation$tc_tertile <- factor(Mitigation$tc_tertile, levels = c("Low", "Medium", "High"))

Recode as factors.

model_mitigation <- lm(mean_hr ~ mean_temp + sex + age + ses, data = Mitigation)

This linear regression model assesses the association between mean daytime temperture (ºC) and mean heart rate (bpm), adjusting for sex, age, and socioeconomic status (SES).

summary(model_mitigation)

Interpretation
A 1°C increase in mean daytime temperature is associated with a 0.96 bpm increase in mean heart rate, adjusting for sex, age, and socioeconomic status (SES). For example, a 5°C increase would correspond to an approximate 4.8 bpm increase in heart rate. The model explains approximately 6.8% of the variance in heart rate. The residual standard error is 11.56, suggesting that predicted heart rate values deviate on average by around ±12 bpm from observed values. Overall, the model is statistically significant (p < 0.001).

Now we will assess effect modification across tertiles.

library(ggeffects)

Load the “ggeffects” package to extract predicted (marginal) effects from regression models, including models with interaction terms. These predictions are adjusted for any confounders included in the model.

model_ndvi_interaction <- lm(mean_hr ~ mean_temp * ndvi_tertile + sex + age + ses, data = Mitigation)
model_tc_interaction <- lm(mean_hr ~ mean_temp * tc_tertile + sex + age + ses, data = Mitigation)

Fit linear regression models with an interaction term.

pred_ndvi <- ggpredict(model_ndvi_interaction, terms = c("mean_temp", "ndvi_tertile"))
pred_tc <- ggpredict(model_tc_interaction, terms = c("mean_temp", "tc_tertile"))

This function calculates model-predicted heart rates across a range of temperature values, separately for each tertile.


library(patchwork)

plot_ndvi <- plot(pred_ndvi) +
  labs(
    title = "Effect Modification by NDVI",
    x = "Mean Daytime Temperature (°C)",
    y = "Predicted Mean Heart Rate (bpm)",
    color = "NDVI"
  ) +
  theme_minimal()

plot_tc <- plot(pred_tc) +
  labs(
    title = "Effect Modification by Tree Cover",
    x = "Mean Daytime Temperature (°C)",
    y = "Predicted Mean Heart Rate (bpm)",
    color = "Tree Cover"
  ) +
  theme_minimal()

plot_ndvi + plot_tc

Interpretation
The plots illustrate that the association between mean daytime temperature and heart rate is modified by surrounding vegetation. In both the NDVI and tree cover models, higher vegetation levels are associated with a progressively weaker temperature–heart rate relationship across tertiles. This pattern suggests that increased vegetation may attenuate the physiological response to heat exposure.

However, such attenuation is more pronounced in the case of tree cover. In areas with high tree cover, the slope is almost flat, indicating substantial mitigation of heat effects. In contrast, the mitigation observed for high NDVI is more modest. These results suggest that, although both metrics provide some protection, tree cover is more effective in mitigating the physiological impacts of heat.

EXERCISE 2: Restoration pathway

This exercise examines how different greenness metrics influence health through the restoration pathway. The restoration pathway describes how exposure to greenness improves health through two major theories: the Attention Restoration Theory (ART) and the Stress Reduction Theory (SRT). The SRT and ART are interconnected, grounded in biophilic principles, emphasizing the innate human connection to nature. According to the biophilia hypothesis, humans have an evolutionary tendency to seek connections with other forms of life (Wilson, 1986).

DESCRIPTION

In this exercise, you will analyze generated data from 5,000 participants to examine how greenness exposure relates to physiological stress, measured through cortisol levels. Greenness is assessed using NDVI within a 500-meter buffer around the home, while weekly time spent in green spaces (minutes) is objectively measured using individual tracking devices.

Restoration <- read_csv("Restoration.csv")
Rows: 5000 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): sex, ses
dbl (5): id, ndvi, green_minutes, cortisol, age
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Load the synthetic dataset titled “Restoration.csv”.

str(Restoration)
spc_tbl_ [5,000 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ id           : num [1:5000] 1 2 3 4 5 6 7 8 9 10 ...
 $ ndvi         : num [1:5000] 0.3981 0.1379 0.1031 0.0156 0.1645 ...
 $ green_minutes: num [1:5000] 42 65 69 0 46 82 46 63 64 57 ...
 $ cortisol     : num [1:5000] 93.7 70.6 85.8 109 118.8 ...
 $ sex          : chr [1:5000] "Female" "Female" "Male" "Male" ...
 $ age          : num [1:5000] 51 48 63 42 30 47 34 36 58 43 ...
 $ ses          : chr [1:5000] "II" "III" "V" "V" ...
 - attr(*, "spec")=
  .. cols(
  ..   id = col_double(),
  ..   ndvi = col_double(),
  ..   green_minutes = col_double(),
  ..   cortisol = col_double(),
  ..   sex = col_character(),
  ..   age = col_double(),
  ..   ses = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

Examine the structure of the dataset. The “Restoration” dataset simulates data for 5,000 adult participants with the following variables:

Restoration$sex <- factor(Restoration$sex, labels = c("Female", "Male"))
Restoration$ses <- factor(Restoration$ses, labels = c("I", "II", "III", "IV", "V"))

Recode categorical variables in the “Restoration” dataset as factor.

skim(Restoration[, c("ndvi", "green_minutes", "cortisol")])
── Data Summary ────────────────────────
                           Values                      
Name                       Restoration[, c("ndvi", "...
Number of rows             5000                        
Number of columns          3                           
_______________________                                
Column type frequency:                                 
  numeric                  3                           
________________________                               
Group variables            None                        

Check the distribution of the exposure and outcome variables.

model_ndvi <- lm(cortisol ~ ndvi + sex + age + ses, data = Restoration)

Fit a linear regression model to examine the relationship between NDVI (exposure) and hair cortisol levels (outcome), adjusting for potential confounders (sex, age, ses).

summary(model_ndvi)

Call:
lm(formula = cortisol ~ ndvi + sex + age + ses, data = Restoration)

Residuals:
    Min      1Q  Median      3Q     Max 
-91.414 -17.447  -0.172  17.602  75.980 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  81.53281    1.97741  41.232  < 2e-16 ***
ndvi        -23.48901    2.74435  -8.559  < 2e-16 ***
sexMale      -4.04010    0.71633  -5.640 1.79e-08 ***
age           0.29469    0.03568   8.260  < 2e-16 ***
sesII         2.73761    1.11360   2.458    0.014 *  
sesIII        5.63268    1.12996   4.985 6.41e-07 ***
sesIV         8.92504    1.12910   7.905 3.28e-15 ***
sesV         12.86420    1.12337  11.451  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 25.29 on 4992 degrees of freedom
Multiple R-squared:  0.06367,   Adjusted R-squared:  0.06235 
F-statistic: 48.49 on 7 and 4992 DF,  p-value: < 2.2e-16

Interpretation
A 1-unit increase in NDVI (from 0 to 1) is associated with a 23.5-unit decrease in hair cortisol, adjusting for other variables. This is difficult to interpret. Using the IQR instead, allows to interpret the effect of NDVI in terms of a typical, realistic change in exposure, making the results clearer.

iqr_ndvi <- IQR(Restoration$ndvi)
Restoration$ndvi_iqr <- Restoration$ndvi/iqr_ndvi
model_ndvi_iqr <- lm(cortisol ~ ndvi_iqr + sex + age + ses, data = Restoration)

Standarize NDVI dividing it by its IQR to make the effect size more interpretable, then model its association with hair cortisol, adjusting for key covariates.

summary(model_ndvi_iqr)

Call:
lm(formula = cortisol ~ ndvi_iqr + sex + age + ses, data = Restoration)

Residuals:
    Min      1Q  Median      3Q     Max 
-91.414 -17.447  -0.172  17.602  75.980 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 81.53281    1.97741  41.232  < 2e-16 ***
ndvi_iqr    -4.30723    0.50324  -8.559  < 2e-16 ***
sexMale     -4.04010    0.71633  -5.640 1.79e-08 ***
age          0.29469    0.03568   8.260  < 2e-16 ***
sesII        2.73761    1.11360   2.458    0.014 *  
sesIII       5.63268    1.12996   4.985 6.41e-07 ***
sesIV        8.92504    1.12910   7.905 3.28e-15 ***
sesV        12.86420    1.12337  11.451  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 25.29 on 4992 degrees of freedom
Multiple R-squared:  0.06367,   Adjusted R-squared:  0.06235 
F-statistic: 48.49 on 7 and 4992 DF,  p-value: < 2.2e-16

Interpretation
A 1 IQR increase in NDVI is associated with a 4.31 pg/mg decrease in cortisol, adjusting for sex, age, and SES. The model explains 6.4% of the variance in hair cortisol levels. The residual standard error of 25.29 is relatively high, meaning that predictions from the model often deviate substantially from actual hair cortisol values. Overall, the model is statistically significant (p < 0.001).

model_time <- lm(cortisol ~ green_minutes + ses + age + sex, data = Restoration)

Fit a linear regression model to examine the relationship between hair cortisol levels (outcome) and mean weekly time spent in green spaces (exposure), adjusting for potential confounders.

summary(model_time)

Call:
lm(formula = cortisol ~ green_minutes + ses + age + sex, data = Restoration)

Residuals:
    Min      1Q  Median      3Q     Max 
-93.191 -17.135  -0.321  17.252  81.090 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)   86.31237    2.07579  41.580  < 2e-16 ***
green_minutes -0.14979    0.01335 -11.223  < 2e-16 ***
sesII          1.91357    1.10992   1.724 0.084758 .  
sesIII         4.19615    1.13207   3.707 0.000212 ***
sesIV          6.88432    1.13954   6.041 1.64e-09 ***
sesV          10.05635    1.14318   8.797  < 2e-16 ***
age            0.27694    0.03556   7.787 8.26e-15 ***
sexMale       -3.93888    0.71249  -5.528 3.40e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 25.16 on 4992 degrees of freedom
Multiple R-squared:  0.07331,   Adjusted R-squared:  0.07201 
F-statistic: 56.41 on 7 and 4992 DF,  p-value: < 2.2e-16

Interpretation
A 1-minute increase in the mean weekly time spent in green spaces is associated with a 0.15 pg/mg decrease in hair cortisol, adjusting for SES, age, and sex. For example, an increase of 30 minutes per week would correspond to a 4.5 pg/mg reduction in cortisol levels. The model explains 7.3% of the variance in hair cortisol levels. The residual standard error is 25.16, indicating that predicted cortisol values often deviate notably from observed values. Overall, the model is statistically significant (p < 0.001).

library(patchwork)

Load the required package to combine ggplot objects.

p1 <- ggplot(Restoration, aes(x = ndvi, y = cortisol)) +
  geom_point(alpha = 0.3, color = "#145A32") +
  geom_smooth(method = "lm", color = "#27AE60", fill = "#ABEBC6") +
  labs(
    title = "NDVI vs. Hair Cortisol",
    x = "NDVI (Residential Greenness)",
    y = "Hair Cortisol (pg/mg)"
  ) +
  theme_minimal(base_size = 10)

Create a scatterplot showing the association between NDVI and hair cortisol levels.

p2 <- ggplot(Restoration, aes(x = green_minutes, y = cortisol)) +
  geom_point(alpha = 0.3, color = "#2C3E50") +
  geom_smooth(method = "lm", color = "#2980B9", fill = "#85C1E9") +
  labs(
    title = "Green Space Time vs. Hair Cortisol",
    x = "Green Space Time (minutes/week)",
    y = "Hair Cortisol (pg/mg)"
  ) +
  theme_minimal(base_size = 10)

Create a second scatterplot on the association between mean weekly time spent in green spaces and hair cortisol levels.

combined_plot <- p1 + p2
combined_plot

Combine plots for comparison using patchwork.

Interpretation
While both “NDVI” and “Green Space Time” are significantly associated with lower hair cortisol, “Green Space Time” shows a stronger statistical association and slightly better model fit. This suggests that while NDVI is a widely available and straightforward greenness metric, the restoration pathway likely involves direct interaction with nature. Therefore, studies should consider not only spatial availability of greenness but also the frequency and duration of individual exposure.

EXERCISE 3: Instoration pathway

This exercise examines how different greenness metrics influence health through the instoration pathway. The instoration or capacity building pathway, highlights how natural environments promote health-related behaviors by encouraging physical activity and social cohesion.

Green spaces often provide a secure, accessible, and attractive setting in which to be physically active. In this regard, numerous studies have found positive associations between increased exposure to green environments and higher levels of physical activity (Gianfredi et al., 2021), which, in turn, is linked to improved physical (Bull et al., 2020) and mental health (Rodriguez-Ayllon et al., 2019).

DESCRIPTION

In this exercise, you will analyze generated data from 5,000 participants to examine how proximity to green spaces relates to physical activity, measured as weekly minutes using individual tracking devices. Greenness exposure is assessed using two different distance measures based on the residential address:

Instoration <- read_csv("Instoration.csv")
Rows: 5000 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (2): sex, ses
dbl (5): id, straight_distance, network_distance, weekly_pa, age
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Load the synthetic dataset titled “Instoration.csv”.

str(Instoration)
spc_tbl_ [5,000 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ id               : num [1:5000] 1 2 3 4 5 6 7 8 9 10 ...
 $ straight_distance: num [1:5000] 433 62 296 341 233 214 188 266 148 503 ...
 $ network_distance : num [1:5000] 904 257 341 682 257 279 377 755 599 791 ...
 $ weekly_pa        : num [1:5000] 292 295 303 305 271 296 315 262 278 280 ...
 $ sex              : chr [1:5000] "Male" "Male" "Male" "Male" ...
 $ age              : num [1:5000] 36 50 43 58 60 38 52 68 54 51 ...
 $ ses              : chr [1:5000] "V" "I" "III" "V" ...
 - attr(*, "spec")=
  .. cols(
  ..   id = col_double(),
  ..   straight_distance = col_double(),
  ..   network_distance = col_double(),
  ..   weekly_pa = col_double(),
  ..   sex = col_character(),
  ..   age = col_double(),
  ..   ses = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

Examine the structure of the dataset. The “Instoration” dataset simulates data for 5,000 adult participants with the following variables:

Instoration$sex <- factor(Instoration$sex, labels = c("Female", "Male"))
Instoration$ses <- factor(Instoration$ses, labels = c("I", "II", "III", "IV", "V"))

Recode categorical variables in the “Instoration” dataset as factor.

skim(Instoration[, c("straight_distance", "network_distance", "weekly_pa")])
── Data Summary ────────────────────────
                           Values                      
Name                       Instoration[, c("straight...
Number of rows             5000                        
Number of columns          3                           
_______________________                                
Column type frequency:                                 
  numeric                  3                           
________________________                               
Group variables            None                        

Check the distribution of the exposure and outcome variables.

model_straight <- lm(weekly_pa ~ straight_distance + sex + age + ses, data = Instoration)

Fit a linear regression model to examine the relationship between straight-line distance to the nearest green space (exposure) and weekly physical activity time (outcome), adjusting for potential confounders (sex, age, ses).

summary(model_straight)

Call:
lm(formula = weekly_pa ~ straight_distance + sex + age + ses, 
    data = Instoration)

Residuals:
    Min      1Q  Median      3Q     Max 
-97.075 -20.316  -0.386  19.883 119.331 

Coefficients:
                    Estimate Std. Error t value Pr(>|t|)    
(Intercept)       300.585497   2.248761 133.667   <2e-16 ***
straight_distance  -0.023692   0.001754 -13.506   <2e-16 ***
sexMale            -1.581549   0.841731  -1.879   0.0603 .  
age                -0.062596   0.037653  -1.662   0.0965 .  
sesII               0.334750   1.311055   0.255   0.7985    
sesIII             -0.119385   1.312486  -0.091   0.9275    
sesIV               1.203676   1.320661   0.911   0.3621    
sesV                0.424646   1.324429   0.321   0.7485    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 29.72 on 4992 degrees of freedom
Multiple R-squared:  0.03637,   Adjusted R-squared:  0.03502 
F-statistic: 26.91 on 7 and 4992 DF,  p-value: < 2.2e-16

Interpretation
A 100-meter increase in straight-line distance to the nearest green space is associated with a 2.37-minute decrease in weekly physical activity, adjusting for sex, age, and socioeconomic status. The model explains 3.6% of the variance in weekly physical activity. The residual standard error indicates a substantial unexplained variability of around 30 minutes. Although the association is statistically significant (p < 0.001), the overall effect size is small, and the explanatory power is limited.

model_network <- lm(weekly_pa ~ network_distance + sex + age + ses, data = Instoration)

Fit a linear regression model to examine the relationship between network distance to the nearest green space (exposure) and weekly physical activity time (outcome), adjusting for potential confounders (sex, age, ses).

summary(model_network)

Call:
lm(formula = weekly_pa ~ network_distance + sex + age + ses, 
    data = Instoration)

Residuals:
    Min      1Q  Median      3Q     Max 
-97.596 -20.786  -0.414  20.064 122.487 

Coefficients:
                   Estimate Std. Error t value Pr(>|t|)    
(Intercept)      306.284376   2.384980 128.422   <2e-16 ***
network_distance  -0.021386   0.001513 -14.132   <2e-16 ***
sexMale           -1.668671   0.840360  -1.986   0.0471 *  
age               -0.063695   0.037591  -1.694   0.0903 .  
sesII              0.347520   1.308872   0.266   0.7906    
sesIII            -0.161458   1.310314  -0.123   0.9019    
sesIV              1.167341   1.318413   0.885   0.3760    
sesV               0.205750   1.322074   0.156   0.8763    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 29.67 on 4992 degrees of freedom
Multiple R-squared:  0.03958,   Adjusted R-squared:  0.03823 
F-statistic: 29.39 on 7 and 4992 DF,  p-value: < 2.2e-16

Interpretation
A 100-meter increase in network distance to the nearest green space is associated with a 2.14-minute decrease in weekly physical activity, adjusting for sex, age, and socioeconomic status. The model explains 4.0% of the variance in weekly physical activity. The residual standard error indicates a substantial unexplained variability of around 30 minutes. Although the association is statistically significant (p < 0.001), the overall effect size is small, and the explanatory power is limited.

p1 <- ggplot(Instoration, aes(x = straight_distance, y = weekly_pa)) +
  geom_point(alpha = 0.3, color = "#ff70a6") +
  geom_smooth(method = "lm", color = "#ff0054", fill = "#F796BB") +
  labs(
    title = "Straight-line vs. Physical Activity",
    x = "Straight-line Green Space (meters)",
    y = "Physical Activity (minutes/week)"
  ) +
  theme_minimal(base_size = 10)

Create a scatterplot showing the association between straight-line distance to the closest green space and weekly physical activity.

p2 <- ggplot(Instoration, aes(x = network_distance, y = weekly_pa)) +
  geom_point(alpha = 0.3, color = "#E4B0EE") +
  geom_smooth(method = "lm", color = "#BE39D8", fill = "#D398DF") +
  labs(
    title = "Network vs. Physical Activity",
    x = "Network Green Space (meters)",
    y = "Physical Activity (minutes/week)"
  ) +
  theme_minimal(base_size = 10)

Create a scatterplot showing the association between network distance to the closest green space and weekly physical activity.

combined_plot <- p1 + p2
combined_plot

Combine plots for comparison using patchwork.

Interpretation
While both “straight-line distance” and “network distance” to the nearest green space are significantly associated with lower weekly physical activity, “network distance” shows a slightly stronger statistical association (t = –14.13 vs. –13.51) and better model fit (R² = 4.0% vs. 3.6%). These results suggest that network distance offers a more realistic estimation of green space accessibility, as it is constructed based on actual routes.

EXERCISE 4: Biodiversity pathway

This exercise focuses on the biodiversity pathway. Biodiversity is a fundamental determinant of health, influencing both physical and psychological well-being. While biodiversity generally benefits human health, it also presents associated risks, including exposure to airborne allergens and volatile organic compounds that may trigger allergic reactions (Marselle et al., 2021).

DESCRIPTION

You will analyze generated data from 4,730 participants to examine how vegetation diversity is associated with allergic rhinitis symptoms (e.g., sneezing, nasal congestion, itchy eyes), measured as the total number of antihistamine pills taken per year.

Vegetation diversity is modeled as a continuous index based on the Shannon diversity index, which accounts for both abundance and evenness of the species present. The index ranges from 0 (no diversity) to approximately 2.5 (high diversity), with higher values indicating greater ecological diversity in the surrounding plant environment.

library(readr)
Biodiversity <- read_csv("Biodiversity.csv")
Rows: 4730 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (3): urbanicity, sex, ses
dbl (4): id, veg_diversity, allergy_med, age
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

Load the synthetic dataset titled “Biodiversity.csv”.

str(Biodiversity)
spc_tbl_ [4,730 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ id           : num [1:4730] 1 2 3 4 5 6 7 8 9 10 ...
 $ veg_diversity: num [1:4730] 1.91 1.37 1.9 2.07 1.56 2.23 1.33 1.46 1.95 1.92 ...
 $ urbanicity   : chr [1:4730] "Suburban" "Urban" "Urban" "Suburban" ...
 $ allergy_med  : num [1:4730] 4 7 7 8 5 12 6 5 11 7 ...
 $ sex          : chr [1:4730] "Male" "Female" "Male" "Male" ...
 $ age          : num [1:4730] 53 40 51 52 39 70 59 44 49 30 ...
 $ ses          : chr [1:4730] "I" "V" "III" "III" ...
 - attr(*, "spec")=
  .. cols(
  ..   id = col_double(),
  ..   veg_diversity = col_double(),
  ..   urbanicity = col_character(),
  ..   allergy_med = col_double(),
  ..   sex = col_character(),
  ..   age = col_double(),
  ..   ses = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

Examine the structure of the dataset. The “Biodiversity” dataset simulates data for 4,730 adult participants with the following variables:

Biodiversity$urbanicity <- factor(Biodiversity$urbanicity, labels = c("Rural", "Suburban", "Urban"))
Biodiversity$sex <- factor(Biodiversity$sex, labels = c("Female", "Male"))
Biodiversity$ses <- factor(Biodiversity$ses, labels = c("I", "II", "III", "IV", "V"))

Recode categorical variables in the “Biodiversity” dataset as factor.

library(skimr)
skim(Biodiversity[, c("veg_diversity", "allergy_med")])
── Data Summary ────────────────────────
                           Values                      
Name                       Biodiversity[, c("veg_div...
Number of rows             4730                        
Number of columns          2                           
_______________________                                
Column type frequency:                                 
  numeric                  2                           
________________________                               
Group variables            None                        

Check the distribution of the exposure and outcome variables.

model_biodiversity <- lm(allergy_med ~ veg_diversity + sex + age + ses, data = Biodiversity)

Fit a linear regression model to examine the relationship between vegetation diversity (exposure) and antihistamine pills per year (outcome), adjusting for potential confounders (sex, age, ses).

summary(model_biodiversity)

Call:
lm(formula = allergy_med ~ veg_diversity + sex + age + ses, data = Biodiversity)

Residuals:
    Min      1Q  Median      3Q     Max 
-9.1043 -2.5355 -0.3814  2.2014 15.2418 

Coefficients:
                Estimate Std. Error t value Pr(>|t|)    
(Intercept)   -1.8879709  0.3396285  -5.559 2.86e-08 ***
veg_diversity  4.5195009  0.1353776  33.384  < 2e-16 ***
sexMale        0.1948230  0.0994269   1.959   0.0501 .  
age            0.0072995  0.0043829   1.665   0.0959 .  
sesII         -0.0001596  0.1551195  -0.001   0.9992    
sesIII        -0.2834895  0.1545145  -1.835   0.0666 .  
sesIV         -0.1052469  0.1560432  -0.674   0.5000    
sesV          -0.2214779  0.1584723  -1.398   0.1623    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 3.418 on 4722 degrees of freedom
Multiple R-squared:  0.193, Adjusted R-squared:  0.1918 
F-statistic: 161.3 on 7 and 4722 DF,  p-value: < 2.2e-16

Interpretation
A unit increase in vegetation diversity is associated with an estimated increase of 4.52 antihistamine pills per year, adjusting for sex, age, and socioeconomic status (p < 0.001). The model explains 19.3% of the variance in antihistamine use, with a residual standard error of 3.42 pills, which indicates a moderate unexplained variability.

library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:data.table’:

    between, first, last

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union
library(broom)

model_coefficients_urbanicity <- Biodiversity %>%
  group_by(urbanicity) %>%
  do(tidy(lm(allergy_med ~ veg_diversity + sex + age + ses, data = .))) %>%
  filter(term == "veg_diversity")  

Fit the previous linear regression model, but this time stratified by urbanization level. This approach allows to examine whether the strength or direction of the association between vegetation diversity and allergic rhinitis symptoms varies across rural, suburban, and urban residential contexts.

print(model_coefficients_urbanicity)

Interpretation
When stratified by urbanization level, the association between vegetation diversity and antihistamine use differs in magnitude. In urban areas, a unit increase in vegetation diversity is associated with an estimated 4.47 pill increase per year (p < 0.001), after adjusting for sex, age, and socioeconomic status. In suburban areas, the increase corresponds to 1.41 pills per year (p < 0.001), while in rural areas, the association is smaller at 0.56 pills per year (p < 0.001). These results suggest that the health impact of vegetation diversity may be modified by urbanization level.

ggplot(Biodiversity, aes(x = veg_diversity, y = allergy_med, color = urbanicity)) +
  geom_point(alpha = 0.4) +
  geom_smooth(method = "lm", se = FALSE, size = 1.2) +
  scale_color_manual(
    values = c("Rural" = "#0BDA51", "Suburban" = "#1E90FF", "Urban" = "#FF3800")  # you can change these
  ) +
  labs(
    title = "Vegetation Diversity vs. Allergy Medication",
    x = "Vegetation Diversity",
    y = "Allergy Medication (pills/year)",
    color = "Urbanization"
  ) +
  theme_minimal()
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

Interpretation
The relationship between urbanization and allergic symptoms (e.g.,asthma, allergic rhinitis, eczema, food allergies) has been widely studied, and epidemiological evidence consistently shows higher prevalence and severity of allergic diseases among individuals residing in urban areas when compared to those that reside in rural settings.This association may be partly attributed to reduced microbial exposure in urban environments. Urbanization has been associated to lower microbial diversity, which is considered an important factor in the development of allergic sensitization. According to the hygiene hypothesis, reduced exposure to microbes in early life limits immune system stimulation, potentially increasing the risk of allergic diseases.

End of the analysis — Thank you for joining the workshop!

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+CiAgPGgxIHN0eWxlPSJmb250LXNpemU6IDQ0cHg7IGNvbG9yOiBncmVlbjsgZm9udC13ZWlnaHQ6IGJvbGQ7IG1hcmdpbi1ib3R0b206IDA7Ij4KICAgIEdyZWVubmVzcyBFeHBvc3VyZSBBc3Nlc3NtZW50IGluIEVudmlyb25tZW50YWwgSGVhbHRoIFJlc2VhcmNoCiAgPC9oMT4KICA8cCBzdHlsZT0iZm9udC1zaXplOiAyMHB4OyBtYXJnaW4tdG9wOiAwOyI+QW1tYW4sIEp1bHkgNXRoIDIwMjU8L3A+CjwvZGl2PgoKPGRpdiBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+CiAgPGgxIHN0eWxlPSJmb250LXNpemU6IDIwcHg7IG1hcmdpbi1ib3R0b206IDA7Ij4KICAgIExlaXJlIEx1cXVlIEdhcmPDrWEKICA8L2gxPgogIDxwIHN0eWxlPSJmb250LXNpemU6IDIwcHg7IG1hcmdpbi10b3A6IDA7Ij4KICAgIFVuaXZlcnNpdHkgb2YgQ2FsaWZvcm5pYSBTYW4gRGllZ28KICA8L3A+CjwvZGl2PgoKClsqKkVYRVJDSVNFIDE6KiogTWl0aWdhdGlvbiBwYXRod2F5XXtzdHlsZT0iZm9udC1zaXplOjI0cHg7IHRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmU7Y29sb3I6Z3JlZW47In0KCkluIHRoaXMgZXhlcmNpc2UsIHdlIGV4cGxvcmUgaG93IGRpZmZlcmVudCBncmVlbm5lc3MgbWV0cmljcyBpbmZsdWVuY2UgaGVhbHRoIHRocm91Z2ggdGhlIG1pdGlnYXRpb24gcGF0aHdheS4gQXMgaGFzIGFscmVhZHkgYmVlbiBub3RlZCwgdGhlIG1pdGlnYXRpb24gcGF0aHdheSBpbmZsdWVuY2VzIGh1bWFuIGhlYWx0aCBieSByZWR1Y2luZyBlbnZpcm9ubWVudGFsIHN0cmVzc29ycywgaW5jbHVkaW5nIGFpciBwb2xsdXRpb24sIGhlYXQsIGFuZCBub2lzZSwgdGhyb3VnaCB0aGUgcHJlc2VuY2Ugb2Ygc3Vycm91bmRpbmcgdmVnZXRhdGlvbi4KCioqREVTQ1JJUFRJT04qKgoKV2UgY29uZHVjdGVkIGEgcHJvc3BlY3RpdmUgc3R1ZHkgaW52b2x2aW5nIDYsMjQzIGFkdWx0IHBhcnRpY2lwYW50cyBtb25pdG9yZWQgZHVyaW5nIHRoZSB3YXJtIHNlYXNvbiAoTWF5IHRvIFNlcHRlbWJlciksIHRvIGludmVzdGlnYXRlIHRoZSBwb3RlbnRpYWwgaW5mbHVlbmNlIG9mIG1lYW4gZGF5dGltZSB0ZW1wZXJhdHVyZSBvbiBoZWFydCByYXRlLCBhbmQgd2hldGhlciB0aGlzIGFzc29jaWF0aW9uIGlzIG1vZGlmaWVkIGJ5IHN1cnJvdW5kaW5nIHZlZ2V0YXRpb24uIEVhY2ggcGFydGljaXBhbnQgd2FzIGVxdWlwcGVkIHdpdGggYSB2YWxpZGF0ZWQgd2VhcmFibGUgZGV2aWNlIGNhcGFibGUgb2YgY29udGludW91c2x5IHJlY29yZGluZyBkYXl0aW1lIGhlYXJ0IHJhdGVzLiBORFZJIGFuZCB0cmVlIGNvdmVyICglKSB3ZXJlIGVzdGltYXRlZCBhdCB0aGUgcmVzaWRlbnRpYWwgbGV2ZWwgdXNpbmcgcmVtb3RlIHNlbnNpbmcgZGF0YSBhZ2dyZWdhdGVkIHdpdGhpbiBhIDUwMC1tZXRlciBidWZmZXIgc3Vycm91bmRpbmcgZWFjaCBwYXJ0aWNpcGFudOKAmXMgaG9tZSBhZGRyZXNzLiBJbiB0aGlzIGFuYWx5c2lzLCBORFZJIGFuZCB0cmVlIGNvdmVyIGFyZSB0cmVhdGVkIGFzIHBvdGVudGlhbCBlZmZlY3QgbW9kaWZpZXJzIG9mIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIGFtYmllbnQgZGF5dGltZSB0ZW1wZXJhdHVyZSBhbmQgcGh5c2lvbG9naWNhbCBzdHJlc3MsIGFzIHJlZmxlY3RlZCBieSBoZWFydCByYXRlLgoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoInJlYWRyIikKaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKQppbnN0YWxsLnBhY2thZ2VzKCJkYXRhLnRhYmxlIikKaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpCmluc3RhbGwucGFja2FnZXMoInNraW1yIikKaW5zdGFsbC5wYWNrYWdlcygicGF0Y2h3b3JrIikKaW5zdGFsbC5wYWNrYWdlcygiYnJvb20iKQppbnN0YWxsLnBhY2thZ2VzKCJnZ2VmZmVjdHMiKQpgYGAKV2Ugd2lsbCBzdGFydCBpbnN0YWxsaW5nIHRoZSByZXF1aXJlZCBwYWNrYWdlcy4KCmBgYHtyfQpsaWJyYXJ5KHJlYWRyKQpNaXRpZ2F0aW9uIDwtIHJlYWRfY3N2KCJNaXRpZ2F0aW9uLmNzdiIpCmBgYApOZXh0LCBsb2FkIHRoZSBzeW50aGV0aWMgZGF0YXNldCB0aXRsZWQgIk1pdGlnYXRpb24uY3N2Ii4KCmBgYHtyfQpzdHIoTWl0aWdhdGlvbikKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJNaXRpZ2F0aW9uIiBkYXRhc2V0IHNpbXVsYXRlcyBkYXRhIGZvciA2LDI0MyBhZHVsdCBwYXJ0aWNpcGFudHMgd2l0aCB0aGUgZm9sbG93aW5nIHZhcmlhYmxlczoKCi0gICAqKmlkKio6IEluZGVudGlmaWNhdGlvbiBudW1iZXIKLSAgICoqbWVhbl90ZW1wKio6IEF2ZXJhZ2UgZGF5dGltZSB0ZW1wZXJhdHVyZSAowrBDKQotICAgKipuZHZpKio6IE5vcm1hbGl6ZWQgRGlmZmVyZW5jZSBWZWdldGF0aW9uIEluZGV4IChORFZJKSB3aXRoaW4gYSA1MDAtbSBidWZmZXIgb2YgdGhlIHJlc2lkZW5jZQotICAgKip0cmVlX2NvdmVyKio6IFBlcmNlbnRhZ2Ugb2YgdHJlZSBjb3ZlciB3aXRoaW4gYSA1MDAtbSBidWZmZXIgb2YgdGhlIHJlc2lkZW5jZQotICAgKiptZWFuX2hyKio6IEF2ZXJhZ2UgZGF5dGltZSBoZWFydCByYXRlIChiZWF0cyBwZXIgbWludXRlKQotICAgKipzZXgqKjogU2V4IChGZW1hbGUgb3IgTWFsZSkKLSAgICoqYWdlKio6IEFnZSAoeWVhcnMpCi0gICAqKnNlcyoqOiBTb2Npb2Vjb25vbWljIHN0YXR1cyAoSSAoaGlnaGVzdCkgdG8gViAobG93ZXN0KSkKCmBgYHtyfQpNaXRpZ2F0aW9uJHNleCA8LSBmYWN0b3IoTWl0aWdhdGlvbiRzZXgsIGxhYmVscyA9IGMoIkZlbWFsZSIsICJNYWxlIikpCk1pdGlnYXRpb24kc2VzIDwtIGZhY3RvcihNaXRpZ2F0aW9uJHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIk1pdGlnYXRpb24iIGRhdGFzZXQgYXMgZmFjdG9yLgoKYGBge3J9CmxpYnJhcnkoc2tpbXIpCmBgYApPYnRhaW4gZGVzY3JpcHRpdmUgc3RhdGlzdGljcyBmb3IgdGhlIGV4cG9zdXJlIGFuZCBvdXRjb21lIHZhcmlhYmxlcyBpbiB0aGUgIk1pdGlnYXRpb24iIGRhdGFzZXQgdXNpbmcgInNraW1yIi4KCmBgYHtyfQpza2ltKE1pdGlnYXRpb25bLCBjKCJtZWFuX3RlbXAiLCAibmR2aSIsICJ0cmVlX2NvdmVyIiwgIm1lYW5faHIiKV0pCmBgYApDaGVjayB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBleHBvc3VyZSBhbmQgb3V0Y29tZSB2YXJpYWJsZXMuIAoKYGBge3J9IAoKTWl0aWdhdGlvbiRuZHZpX3RlcnRpbGUgPC0gY3V0KE1pdGlnYXRpb24kbmR2aSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gcXVhbnRpbGUoTWl0aWdhdGlvbiRuZHZpLCBwcm9icyA9IGMoMCwgMS8zLCAyLzMsIDEpLCBuYS5ybSA9IFRSVUUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIpKQoKTWl0aWdhdGlvbiR0Y190ZXJ0aWxlIDwtIGN1dChNaXRpZ2F0aW9uJHRyZWVfY292ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBxdWFudGlsZShNaXRpZ2F0aW9uJHRyZWVfY292ZXIsIHByb2JzID0gYygwLCAxLzMsIDIvMywgMSksIG5hLnJtID0gVFJVRSksCiAgICAgICAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJMb3ciLCAiTWVkaXVtIiwgIkhpZ2giKSkKCmBgYApDcmVhdGUgdGVydGlsZXMgZm9yIE5EVkkgYW5kIHRyZWUgY292ZXIuCgpgYGB7cn0KTWl0aWdhdGlvbiRuZHZpX3RlcnRpbGUgPC0gZmFjdG9yKE1pdGlnYXRpb24kbmR2aV90ZXJ0aWxlLCBsZXZlbHMgPSBjKCJMb3ciLCAiTWVkaXVtIiwgIkhpZ2giKSkKTWl0aWdhdGlvbiR0Y190ZXJ0aWxlIDwtIGZhY3RvcihNaXRpZ2F0aW9uJHRjX3RlcnRpbGUsIGxldmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIpKQpgYGAKUmVjb2RlIGFzIGZhY3RvcnMuCgpgYGB7cn0KbW9kZWxfbWl0aWdhdGlvbiA8LSBsbShtZWFuX2hyIH4gbWVhbl90ZW1wICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gTWl0aWdhdGlvbikKYGBgClRoaXMgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgYXNzZXNzZXMgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gbWVhbiBkYXl0aW1lIHRlbXBlcnR1cmUgKMK6QykgYW5kIG1lYW4gaGVhcnQgcmF0ZSAoYnBtKSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIChTRVMpLiAKCmBgYHtyfQpzdW1tYXJ5KG1vZGVsX21pdGlnYXRpb24pCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBBIDHCsEMgaW5jcmVhc2UgaW4gbWVhbiBkYXl0aW1lIHRlbXBlcmF0dXJlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDAuOTYgYnBtIGluY3JlYXNlIGluIG1lYW4gaGVhcnQgcmF0ZSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIChTRVMpLiBGb3IgZXhhbXBsZSwgYSA1wrBDIGluY3JlYXNlIHdvdWxkIGNvcnJlc3BvbmQgdG8gYW4gYXBwcm94aW1hdGUgNC44IGJwbSBpbmNyZWFzZSBpbiBoZWFydCByYXRlLiBUaGUgbW9kZWwgZXhwbGFpbnMgYXBwcm94aW1hdGVseSA2LjglIG9mIHRoZSB2YXJpYW5jZSBpbiBoZWFydCByYXRlLiBUaGUgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3IgaXMgMTEuNTYsIHN1Z2dlc3RpbmcgdGhhdCBwcmVkaWN0ZWQgaGVhcnQgcmF0ZSB2YWx1ZXMgZGV2aWF0ZSBvbiBhdmVyYWdlIGJ5IGFyb3VuZCDCsTEyIGJwbSBmcm9tIG9ic2VydmVkIHZhbHVlcy4gT3ZlcmFsbCwgdGhlIG1vZGVsIGlzIHN0YXRpc3RpY2FsbHkgc2lnbmlmaWNhbnQgKHAgJmx0OyAwLjAwMSkuCjwvZGl2PgoKTm93IHdlIHdpbGwgYXNzZXNzIGVmZmVjdCBtb2RpZmljYXRpb24gYWNyb3NzIHRlcnRpbGVzLgoKYGBge3J9CmxpYnJhcnkoZ2dlZmZlY3RzKQpgYGAKTG9hZCB0aGUgImdnZWZmZWN0cyIgcGFja2FnZSB0byBleHRyYWN0IHByZWRpY3RlZCAobWFyZ2luYWwpIGVmZmVjdHMgZnJvbSByZWdyZXNzaW9uIG1vZGVscywgaW5jbHVkaW5nIG1vZGVscyB3aXRoIGludGVyYWN0aW9uIHRlcm1zLiBUaGVzZSBwcmVkaWN0aW9ucyBhcmUgYWRqdXN0ZWQgZm9yIGFueSBjb25mb3VuZGVycyBpbmNsdWRlZCBpbiB0aGUgbW9kZWwuCgpgYGB7cn0KbW9kZWxfbmR2aV9pbnRlcmFjdGlvbiA8LSBsbShtZWFuX2hyIH4gbWVhbl90ZW1wICogbmR2aV90ZXJ0aWxlICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gTWl0aWdhdGlvbikKbW9kZWxfdGNfaW50ZXJhY3Rpb24gPC0gbG0obWVhbl9ociB+IG1lYW5fdGVtcCAqIHRjX3RlcnRpbGUgKyBzZXggKyBhZ2UgKyBzZXMsIGRhdGEgPSBNaXRpZ2F0aW9uKQpgYGAKRml0IGxpbmVhciByZWdyZXNzaW9uIG1vZGVscyB3aXRoIGFuIGludGVyYWN0aW9uIHRlcm0uCgpgYGB7cn0KcHJlZF9uZHZpIDwtIGdncHJlZGljdChtb2RlbF9uZHZpX2ludGVyYWN0aW9uLCB0ZXJtcyA9IGMoIm1lYW5fdGVtcCIsICJuZHZpX3RlcnRpbGUiKSkKcHJlZF90YyA8LSBnZ3ByZWRpY3QobW9kZWxfdGNfaW50ZXJhY3Rpb24sIHRlcm1zID0gYygibWVhbl90ZW1wIiwgInRjX3RlcnRpbGUiKSkKYGBgClRoaXMgZnVuY3Rpb24gY2FsY3VsYXRlcyBtb2RlbC1wcmVkaWN0ZWQgaGVhcnQgcmF0ZXMgYWNyb3NzIGEgcmFuZ2Ugb2YgdGVtcGVyYXR1cmUgdmFsdWVzLCBzZXBhcmF0ZWx5IGZvciBlYWNoIHRlcnRpbGUuCgpgYGB7cn0KCmxpYnJhcnkocGF0Y2h3b3JrKQoKcGxvdF9uZHZpIDwtIHBsb3QocHJlZF9uZHZpKSArCiAgbGFicygKICAgIHRpdGxlID0gIkVmZmVjdCBNb2RpZmljYXRpb24gYnkgTkRWSSIsCiAgICB4ID0gIk1lYW4gRGF5dGltZSBUZW1wZXJhdHVyZSAowrBDKSIsCiAgICB5ID0gIlByZWRpY3RlZCBNZWFuIEhlYXJ0IFJhdGUgKGJwbSkiLAogICAgY29sb3IgPSAiTkRWSSIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCnBsb3RfdGMgPC0gcGxvdChwcmVkX3RjKSArCiAgbGFicygKICAgIHRpdGxlID0gIkVmZmVjdCBNb2RpZmljYXRpb24gYnkgVHJlZSBDb3ZlciIsCiAgICB4ID0gIk1lYW4gRGF5dGltZSBUZW1wZXJhdHVyZSAowrBDKSIsCiAgICB5ID0gIlByZWRpY3RlZCBNZWFuIEhlYXJ0IFJhdGUgKGJwbSkiLAogICAgY29sb3IgPSAiVHJlZSBDb3ZlciIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCnBsb3RfbmR2aSArIHBsb3RfdGMKCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPgpUaGUgcGxvdHMgaWxsdXN0cmF0ZSB0aGF0IHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIG1lYW4gZGF5dGltZSB0ZW1wZXJhdHVyZSBhbmQgaGVhcnQgcmF0ZSBpcyBtb2RpZmllZCBieSBzdXJyb3VuZGluZyB2ZWdldGF0aW9uLiBJbiBib3RoIHRoZSBORFZJIGFuZCB0cmVlIGNvdmVyIG1vZGVscywgaGlnaGVyIHZlZ2V0YXRpb24gbGV2ZWxzIGFyZSBhc3NvY2lhdGVkIHdpdGggYSBwcm9ncmVzc2l2ZWx5IHdlYWtlciB0ZW1wZXJhdHVyZeKAk2hlYXJ0IHJhdGUgcmVsYXRpb25zaGlwIGFjcm9zcyB0ZXJ0aWxlcy4gVGhpcyBwYXR0ZXJuIHN1Z2dlc3RzIHRoYXQgaW5jcmVhc2VkIHZlZ2V0YXRpb24gbWF5IGF0dGVudWF0ZSB0aGUgcGh5c2lvbG9naWNhbCByZXNwb25zZSB0byBoZWF0IGV4cG9zdXJlLgoKSG93ZXZlciwgc3VjaCBhdHRlbnVhdGlvbiBpcyBtb3JlIHByb25vdW5jZWQgaW4gdGhlIGNhc2Ugb2YgdHJlZSBjb3Zlci4gSW4gYXJlYXMgd2l0aCBoaWdoIHRyZWUgY292ZXIsIHRoZSBzbG9wZSBpcyBhbG1vc3QgZmxhdCwgaW5kaWNhdGluZyBzdWJzdGFudGlhbCBtaXRpZ2F0aW9uIG9mIGhlYXQgZWZmZWN0cy4gSW4gY29udHJhc3QsIHRoZSBtaXRpZ2F0aW9uIG9ic2VydmVkIGZvciBoaWdoIE5EVkkgaXMgbW9yZSBtb2Rlc3QuIFRoZXNlIHJlc3VsdHMgc3VnZ2VzdCB0aGF0LCBhbHRob3VnaCBib3RoIG1ldHJpY3MgcHJvdmlkZSBzb21lIHByb3RlY3Rpb24sIHRyZWUgY292ZXIgaXMgbW9yZSBlZmZlY3RpdmUgaW4gbWl0aWdhdGluZyB0aGUgcGh5c2lvbG9naWNhbCBpbXBhY3RzIG9mIGhlYXQuIAoKCjwvZGl2PgoKWyoqRVhFUkNJU0UgMjoqKiBSZXN0b3JhdGlvbiBwYXRod2F5XXtzdHlsZT0iZm9udC1zaXplOjI0cHg7IHRleHQtZGVjb3JhdGlvbjp1bmRlcmxpbmU7Y29sb3I6Z3JlZW47In0KClRoaXMgZXhlcmNpc2UgZXhhbWluZXMgaG93IGRpZmZlcmVudCBncmVlbm5lc3MgbWV0cmljcyBpbmZsdWVuY2UgaGVhbHRoIHRocm91Z2ggdGhlIHJlc3RvcmF0aW9uIHBhdGh3YXkuIFRoZSByZXN0b3JhdGlvbiBwYXRod2F5IGRlc2NyaWJlcyBob3cgZXhwb3N1cmUgdG8gZ3JlZW5uZXNzIGltcHJvdmVzIGhlYWx0aCB0aHJvdWdoIHR3byBtYWpvciB0aGVvcmllczogdGhlICoqQXR0ZW50aW9uIFJlc3RvcmF0aW9uIFRoZW9yeSAoQVJUKSoqIGFuZCB0aGUgKipTdHJlc3MgUmVkdWN0aW9uIFRoZW9yeSAoU1JUKSoqLiBUaGUgU1JUIGFuZCBBUlQgYXJlIGludGVyY29ubmVjdGVkLCBncm91bmRlZCBpbiBiaW9waGlsaWMgcHJpbmNpcGxlcywgZW1waGFzaXppbmcgdGhlIGlubmF0ZSBodW1hbiBjb25uZWN0aW9uIHRvIG5hdHVyZS4gQWNjb3JkaW5nIHRvIHRoZSBiaW9waGlsaWEgaHlwb3RoZXNpcywgaHVtYW5zIGhhdmUgYW4gZXZvbHV0aW9uYXJ5IHRlbmRlbmN5IHRvIHNlZWsgY29ubmVjdGlvbnMgd2l0aCBvdGhlciBmb3JtcyBvZiBsaWZlIChXaWxzb24sIDE5ODYpLgoKKipERVNDUklQVElPTioqCgpJbiB0aGlzIGV4ZXJjaXNlLCB5b3Ugd2lsbCBhbmFseXplIGdlbmVyYXRlZCBkYXRhIGZyb20gNSwwMDAgcGFydGljaXBhbnRzIHRvIGV4YW1pbmUgaG93IGdyZWVubmVzcyBleHBvc3VyZSByZWxhdGVzIHRvIHBoeXNpb2xvZ2ljYWwgc3RyZXNzLCBtZWFzdXJlZCB0aHJvdWdoIGNvcnRpc29sIGxldmVscy4gR3JlZW5uZXNzIGlzIGFzc2Vzc2VkIHVzaW5nIE5EVkkgd2l0aGluIGEgNTAwLW1ldGVyIGJ1ZmZlciBhcm91bmQgdGhlIGhvbWUsIHdoaWxlIHdlZWtseSB0aW1lIHNwZW50IGluIGdyZWVuIHNwYWNlcyAobWludXRlcykgaXMgb2JqZWN0aXZlbHkgbWVhc3VyZWQgdXNpbmcgaW5kaXZpZHVhbCB0cmFja2luZyBkZXZpY2VzLgoKYGBge3J9ClJlc3RvcmF0aW9uIDwtIHJlYWRfY3N2KCJSZXN0b3JhdGlvbi5jc3YiKQpgYGAKTG9hZCB0aGUgc3ludGhldGljIGRhdGFzZXQgdGl0bGVkICJSZXN0b3JhdGlvbi5jc3YiLgoKYGBge3J9CnN0cihSZXN0b3JhdGlvbikKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJSZXN0b3JhdGlvbiIgZGF0YXNldCBzaW11bGF0ZXMgZGF0YSBmb3IgNSwwMDAgYWR1bHQgcGFydGljaXBhbnRzIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6CgotICAgKippZCoqOiBJbmRlbnRpZmljYXRpb24gbnVtYmVyCi0gICAqKm5kdmkqKjogTm9ybWFsaXplZCBEaWZmZXJlbmNlIFZlZ2V0YXRpb24gSW5kZXggKE5EVkkpIHdpdGhpbiBhIDUwMC1tIGJ1ZmZlciBvZiB0aGUgcmVzaWRlbmNlCi0gICAqKmdyZWVuX21pbnV0ZXMqKjogTWVhbiB3ZWVrbHkgdGltZSBzcGVudCBpbiBncmVlbiBzcGFjZXMgKG1pbnV0ZXMpCi0gICAqKmNvcnRpc29sKio6IEhhaXIgY29ydGlzb2wgbWVhc3VyZXMgKHBnL21nKQotICAgKipzZXgqKjogU2V4IChGZW1hbGUgb3IgTWFsZSkKLSAgICoqYWdlKio6IEFnZSAoeWVhcnMpCi0gICAqKnNlcyoqOiBTb2Npb2Vjb25vbWljIHN0YXR1cywgKEkgKGhpZ2hlc3QpIHRvIFYgKGxvd2VzdCkpCgoKYGBge3J9ClJlc3RvcmF0aW9uJHNleCA8LSBmYWN0b3IoUmVzdG9yYXRpb24kc2V4LCBsYWJlbHMgPSBjKCJGZW1hbGUiLCAiTWFsZSIpKQpSZXN0b3JhdGlvbiRzZXMgPC0gZmFjdG9yKFJlc3RvcmF0aW9uJHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIlJlc3RvcmF0aW9uIiBkYXRhc2V0IGFzIGZhY3Rvci4KCmBgYHtyfQpza2ltKFJlc3RvcmF0aW9uWywgYygibmR2aSIsICJncmVlbl9taW51dGVzIiwgImNvcnRpc29sIildKQpgYGAKQ2hlY2sgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXhwb3N1cmUgYW5kIG91dGNvbWUgdmFyaWFibGVzLiAKCmBgYHtyfQptb2RlbF9uZHZpIDwtIGxtKGNvcnRpc29sIH4gbmR2aSArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IFJlc3RvcmF0aW9uKQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gTkRWSSAoZXhwb3N1cmUpIGFuZCBoYWlyIGNvcnRpc29sIGxldmVscyAob3V0Y29tZSksIGFkanVzdGluZyBmb3IgcG90ZW50aWFsIGNvbmZvdW5kZXJzIChzZXgsIGFnZSwgc2VzKS4gCgpgYGB7cn0Kc3VtbWFyeShtb2RlbF9uZHZpKQpgYGAKPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuOyBmb250LWZhbWlseTogJ0dlb3JnaWEnLCBzZXJpZjsgZm9udC1zaXplOiAxNnB4OyBmb250LXdlaWdodDogbm9ybWFsOyI+CiAgPHN0cm9uZz5JbnRlcnByZXRhdGlvbjwvc3Ryb25nPjxicj4gQSAxLXVuaXQgaW5jcmVhc2UgaW4gTkRWSSAoZnJvbSAwIHRvIDEpIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDIzLjUtdW5pdCBkZWNyZWFzZSBpbiBoYWlyIGNvcnRpc29sLCBhZGp1c3RpbmcgZm9yIG90aGVyIHZhcmlhYmxlcy4gVGhpcyBpcyBkaWZmaWN1bHQgdG8gaW50ZXJwcmV0LiAKVXNpbmcgdGhlIElRUiBpbnN0ZWFkLCBhbGxvd3MgdG8gaW50ZXJwcmV0IHRoZSBlZmZlY3Qgb2YgTkRWSSBpbiB0ZXJtcyBvZiBhIHR5cGljYWwsIHJlYWxpc3RpYyBjaGFuZ2UgaW4gZXhwb3N1cmUsIG1ha2luZyB0aGUgcmVzdWx0cyBjbGVhcmVyLgo8L2Rpdj4KCgpgYGB7cn0KaXFyX25kdmkgPC0gSVFSKFJlc3RvcmF0aW9uJG5kdmkpClJlc3RvcmF0aW9uJG5kdmlfaXFyIDwtIFJlc3RvcmF0aW9uJG5kdmkvaXFyX25kdmkKbW9kZWxfbmR2aV9pcXIgPC0gbG0oY29ydGlzb2wgfiBuZHZpX2lxciArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IFJlc3RvcmF0aW9uKQpgYGAKU3RhbmRhcml6ZSBORFZJIGRpdmlkaW5nIGl0IGJ5IGl0cyBJUVIgdG8gbWFrZSB0aGUgZWZmZWN0IHNpemUgbW9yZSBpbnRlcnByZXRhYmxlLCB0aGVuIG1vZGVsIGl0cyBhc3NvY2lhdGlvbiB3aXRoIGhhaXIgY29ydGlzb2wsIGFkanVzdGluZyBmb3Iga2V5IGNvdmFyaWF0ZXMuCgpgYGB7cn0Kc3VtbWFyeShtb2RlbF9uZHZpX2lxcikKYGBgCjxkaXYgc3R5bGU9ImNvbG9yOiBncmVlbjsgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgc2VyaWY7IGZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IG5vcm1hbDsiPgogIDxzdHJvbmc+SW50ZXJwcmV0YXRpb248L3N0cm9uZz48YnI+IEEgMSBJUVIgaW5jcmVhc2UgaW4gTkRWSSBpcyBhc3NvY2lhdGVkIHdpdGggYSA0LjMxIHBnL21nIGRlY3JlYXNlIGluIGNvcnRpc29sLCBhZGp1c3RpbmcgZm9yIHNleCwgYWdlLCBhbmQgU0VTLiBUaGUgbW9kZWwgZXhwbGFpbnMgNi40JSBvZiB0aGUgdmFyaWFuY2UgaW4gaGFpciBjb3J0aXNvbCBsZXZlbHMuIFRoZSByZXNpZHVhbCBzdGFuZGFyZCBlcnJvciBvZiAyNS4yOSBpcyByZWxhdGl2ZWx5IGhpZ2gsIG1lYW5pbmcgdGhhdCBwcmVkaWN0aW9ucyBmcm9tIHRoZSBtb2RlbCBvZnRlbiBkZXZpYXRlIHN1YnN0YW50aWFsbHkgZnJvbSBhY3R1YWwgaGFpciBjb3J0aXNvbCB2YWx1ZXMuIE92ZXJhbGwsIHRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLgo8L2Rpdj4KCmBgYHtyfQptb2RlbF90aW1lIDwtIGxtKGNvcnRpc29sIH4gZ3JlZW5fbWludXRlcyArIHNlcyArIGFnZSArIHNleCwgZGF0YSA9IFJlc3RvcmF0aW9uKQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gaGFpciBjb3J0aXNvbCBsZXZlbHMgKG91dGNvbWUpIGFuZCBtZWFuIHdlZWtseSB0aW1lIHNwZW50IGluIGdyZWVuIHNwYWNlcyAoZXhwb3N1cmUpLCBhZGp1c3RpbmcgZm9yIHBvdGVudGlhbCBjb25mb3VuZGVycy4gCgpgYGB7cn0Kc3VtbWFyeShtb2RlbF90aW1lKQpgYGAKPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuOyBmb250LWZhbWlseTogJ0dlb3JnaWEnLCBzZXJpZjsgZm9udC1zaXplOiAxNnB4OyBmb250LXdlaWdodDogbm9ybWFsOyI+CiAgPHN0cm9uZz5JbnRlcnByZXRhdGlvbjwvc3Ryb25nPjxicj4KQSAxLW1pbnV0ZSBpbmNyZWFzZSBpbiB0aGUgbWVhbiB3ZWVrbHkgdGltZSBzcGVudCBpbiBncmVlbiBzcGFjZXMgaXMgYXNzb2NpYXRlZCB3aXRoIGEgMC4xNSBwZy9tZyBkZWNyZWFzZSBpbiBoYWlyIGNvcnRpc29sLCBhZGp1c3RpbmcgZm9yIFNFUywgYWdlLCBhbmQgc2V4LiBGb3IgZXhhbXBsZSwgYW4gaW5jcmVhc2Ugb2YgMzAgbWludXRlcyBwZXIgd2VlayB3b3VsZCBjb3JyZXNwb25kIHRvIGEgNC41IHBnL21nIHJlZHVjdGlvbiBpbiBjb3J0aXNvbCBsZXZlbHMuIFRoZSBtb2RlbCBleHBsYWlucyA3LjMlIG9mIHRoZSB2YXJpYW5jZSBpbiBoYWlyIGNvcnRpc29sIGxldmVscy4gVGhlIHJlc2lkdWFsIHN0YW5kYXJkIGVycm9yIGlzIDI1LjE2LCBpbmRpY2F0aW5nIHRoYXQgcHJlZGljdGVkIGNvcnRpc29sIHZhbHVlcyBvZnRlbiBkZXZpYXRlIG5vdGFibHkgZnJvbSBvYnNlcnZlZCB2YWx1ZXMuIE92ZXJhbGwsIHRoZSBtb2RlbCBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLgo8L2Rpdj4KCgpgYGB7cn0KbGlicmFyeShwYXRjaHdvcmspCmBgYApMb2FkIHRoZSByZXF1aXJlZCBwYWNrYWdlIHRvIGNvbWJpbmUgZ2dwbG90IG9iamVjdHMuCgpgYGB7cn0KcDEgPC0gZ2dwbG90KFJlc3RvcmF0aW9uLCBhZXMoeCA9IG5kdmksIHkgPSBjb3J0aXNvbCkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC4zLCBjb2xvciA9ICIjMTQ1QTMyIikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG9yID0gIiMyN0FFNjAiLCBmaWxsID0gIiNBQkVCQzYiKSArCiAgbGFicygKICAgIHRpdGxlID0gIk5EVkkgdnMuIEhhaXIgQ29ydGlzb2wiLAogICAgeCA9ICJORFZJIChSZXNpZGVudGlhbCBHcmVlbm5lc3MpIiwKICAgIHkgPSAiSGFpciBDb3J0aXNvbCAocGcvbWcpIgogICkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApCmBgYApDcmVhdGUgYSBzY2F0dGVycGxvdCBzaG93aW5nIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIE5EVkkgYW5kIGhhaXIgY29ydGlzb2wgbGV2ZWxzLgoKYGBge3J9CnAyIDwtIGdncGxvdChSZXN0b3JhdGlvbiwgYWVzKHggPSBncmVlbl9taW51dGVzLCB5ID0gY29ydGlzb2wpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMywgY29sb3IgPSAiIzJDM0U1MCIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICIjMjk4MEI5IiwgZmlsbCA9ICIjODVDMUU5IikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJHcmVlbiBTcGFjZSBUaW1lIHZzLiBIYWlyIENvcnRpc29sIiwKICAgIHggPSAiR3JlZW4gU3BhY2UgVGltZSAobWludXRlcy93ZWVrKSIsCiAgICB5ID0gIkhhaXIgQ29ydGlzb2wgKHBnL21nKSIKICApICsKICB0aGVtZV9taW5pbWFsKGJhc2Vfc2l6ZSA9IDEwKQpgYGAKQ3JlYXRlIGEgc2Vjb25kIHNjYXR0ZXJwbG90IG9uIHRoZSBhc3NvY2lhdGlvbiBiZXR3ZWVuIG1lYW4gd2Vla2x5IHRpbWUgc3BlbnQgaW4gZ3JlZW4gc3BhY2VzIGFuZCBoYWlyIGNvcnRpc29sIGxldmVscy4KCmBgYHtyfQpjb21iaW5lZF9wbG90IDwtIHAxICsgcDIKY29tYmluZWRfcGxvdApgYGAKQ29tYmluZSBwbG90cyBmb3IgY29tcGFyaXNvbiB1c2luZyBwYXRjaHdvcmsuCgo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBXaGlsZSBib3RoICJORFZJIiBhbmQgIkdyZWVuIFNwYWNlIFRpbWUiIGFyZSBzaWduaWZpY2FudGx5IGFzc29jaWF0ZWQgd2l0aCBsb3dlciBoYWlyIGNvcnRpc29sLCAiR3JlZW4gU3BhY2UgVGltZSIgc2hvd3MgYSBzdHJvbmdlciBzdGF0aXN0aWNhbCBhc3NvY2lhdGlvbiBhbmQgc2xpZ2h0bHkgYmV0dGVyIG1vZGVsIGZpdC4gVGhpcyBzdWdnZXN0cyB0aGF0IHdoaWxlIE5EVkkgaXMgYSB3aWRlbHkgYXZhaWxhYmxlIGFuZCBzdHJhaWdodGZvcndhcmQgZ3JlZW5uZXNzIG1ldHJpYywgdGhlIHJlc3RvcmF0aW9uIHBhdGh3YXkgbGlrZWx5IGludm9sdmVzIGRpcmVjdCBpbnRlcmFjdGlvbiB3aXRoIG5hdHVyZS4gVGhlcmVmb3JlLCBzdHVkaWVzIHNob3VsZCBjb25zaWRlciBub3Qgb25seSBzcGF0aWFsIGF2YWlsYWJpbGl0eSBvZiBncmVlbm5lc3MgYnV0IGFsc28gdGhlIGZyZXF1ZW5jeSBhbmQgZHVyYXRpb24gb2YgaW5kaXZpZHVhbCBleHBvc3VyZS4KPC9kaXY+CgpbKipFWEVSQ0lTRSAzOioqIEluc3RvcmF0aW9uIHBhdGh3YXlde3N0eWxlPSJmb250LXNpemU6MjRweDsgdGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZTtjb2xvcjpncmVlbjsifQoKVGhpcyBleGVyY2lzZSBleGFtaW5lcyBob3cgZGlmZmVyZW50IGdyZWVubmVzcyBtZXRyaWNzIGluZmx1ZW5jZSBoZWFsdGggdGhyb3VnaCB0aGUgaW5zdG9yYXRpb24gcGF0aHdheS4gVGhlIGluc3RvcmF0aW9uIG9yIGNhcGFjaXR5IGJ1aWxkaW5nIHBhdGh3YXksIGhpZ2hsaWdodHMgaG93IG5hdHVyYWwgZW52aXJvbm1lbnRzIHByb21vdGUgaGVhbHRoLXJlbGF0ZWQgYmVoYXZpb3JzIGJ5IGVuY291cmFnaW5nIHBoeXNpY2FsIGFjdGl2aXR5IGFuZCBzb2NpYWwgY29oZXNpb24uCgpHcmVlbiBzcGFjZXMgb2Z0ZW4gcHJvdmlkZSBhIHNlY3VyZSwgYWNjZXNzaWJsZSwgYW5kIGF0dHJhY3RpdmUgc2V0dGluZyBpbiB3aGljaAp0byBiZSBwaHlzaWNhbGx5IGFjdGl2ZS4gSW4gdGhpcyByZWdhcmQsIG51bWVyb3VzIHN0dWRpZXMgaGF2ZSBmb3VuZCBwb3NpdGl2ZSBhc3NvY2lhdGlvbnMgYmV0d2VlbiBpbmNyZWFzZWQgZXhwb3N1cmUgdG8gZ3JlZW4gZW52aXJvbm1lbnRzIGFuZCBoaWdoZXIgbGV2ZWxzIG9mIHBoeXNpY2FsIGFjdGl2aXR5IChHaWFuZnJlZGkgZXQgYWwuLCAyMDIxKSwgd2hpY2gsIGluIHR1cm4sIGlzIGxpbmtlZCB0byBpbXByb3ZlZCBwaHlzaWNhbCAoQnVsbCBldCBhbC4sIDIwMjApIGFuZCBtZW50YWwgaGVhbHRoIChSb2RyaWd1ZXotQXlsbG9uIGV0IGFsLiwgMjAxOSkuCgoqKkRFU0NSSVBUSU9OKioKCkluIHRoaXMgZXhlcmNpc2UsIHlvdSB3aWxsIGFuYWx5emUgZ2VuZXJhdGVkIGRhdGEgZnJvbSA1LDAwMCBwYXJ0aWNpcGFudHMgdG8gZXhhbWluZSBob3cgcHJveGltaXR5IHRvIGdyZWVuIHNwYWNlcyByZWxhdGVzIHRvIHBoeXNpY2FsIGFjdGl2aXR5LCBtZWFzdXJlZCBhcyB3ZWVrbHkgbWludXRlcyB1c2luZyBpbmRpdmlkdWFsIHRyYWNraW5nIGRldmljZXMuIEdyZWVubmVzcyBleHBvc3VyZSBpcyBhc3Nlc3NlZCB1c2luZyB0d28gZGlmZmVyZW50IGRpc3RhbmNlIG1lYXN1cmVzIGJhc2VkIG9uIHRoZSByZXNpZGVudGlhbCBhZGRyZXNzOiAKCi0gICBTdHJhaWdodC1saW5lIGRpc3RhbmNlIHRvIHRoZSBjbG9zZXN0IGdyZWVuIHNwYWNlIChpbiBtZXRlcnMpCi0gICBOZXR3b3JrIGRpc3RhbmNlIHRvIHRoZSBjbG9zZXN0IGdyZWVuIHNwYWNlIChpbiBtZXRlcnMpCgoKYGBge3J9Ckluc3RvcmF0aW9uIDwtIHJlYWRfY3N2KCJJbnN0b3JhdGlvbi5jc3YiKQpgYGAKTG9hZCB0aGUgc3ludGhldGljIGRhdGFzZXQgdGl0bGVkICJJbnN0b3JhdGlvbi5jc3YiLgoKYGBge3J9CnN0cihJbnN0b3JhdGlvbikKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJJbnN0b3JhdGlvbiIgZGF0YXNldCBzaW11bGF0ZXMgZGF0YSBmb3IgNSwwMDAgYWR1bHQgcGFydGljaXBhbnRzIHdpdGggdGhlIGZvbGxvd2luZyB2YXJpYWJsZXM6CgotICAgKippZCoqOiBJbmRlbnRpZmljYXRpb24gbnVtYmVyCi0gICAqKnN0cmFpZ2h0X2Rpc3RhbmNlKio6IFN0cmFpZ2h0LWxpbmUgZGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UgKG1ldGVycykgYmFzZWQgb24gdGhlIHJlc2lkZW5jZQotICAgKipuZXR3b3JrX2Rpc3RhbmNlKio6IE5ldHdvcmsgZGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UgKG1ldGVycykgYmFzZWQgb24gdGhlIHJlc2lkZW5jZQotICAgKip3ZWVrbHlfcGEqKjogV2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5IChtaW51dGVzKQotICAgKipzZXgqKjogU2V4IChGZW1hbGUgb3IgTWFsZSkKLSAgICoqYWdlKio6IEFnZSAoeWVhcnMpCi0gICAqKnNlcyoqOiBTb2Npb2Vjb25vbWljIHN0YXR1cywgKEkgKGhpZ2hlc3QpIHRvIFYgKGxvd2VzdCkpCgoKYGBge3J9Ckluc3RvcmF0aW9uJHNleCA8LSBmYWN0b3IoSW5zdG9yYXRpb24kc2V4LCBsYWJlbHMgPSBjKCJGZW1hbGUiLCAiTWFsZSIpKQpJbnN0b3JhdGlvbiRzZXMgPC0gZmFjdG9yKEluc3RvcmF0aW9uJHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIkluc3RvcmF0aW9uIiBkYXRhc2V0IGFzIGZhY3Rvci4KCmBgYHtyfQpza2ltKEluc3RvcmF0aW9uWywgYygic3RyYWlnaHRfZGlzdGFuY2UiLCAibmV0d29ya19kaXN0YW5jZSIsICJ3ZWVrbHlfcGEiKV0pCmBgYApDaGVjayB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBleHBvc3VyZSBhbmQgb3V0Y29tZSB2YXJpYWJsZXMuIAoKYGBge3J9Cm1vZGVsX3N0cmFpZ2h0IDwtIGxtKHdlZWtseV9wYSB+IHN0cmFpZ2h0X2Rpc3RhbmNlICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gSW5zdG9yYXRpb24pCmBgYApGaXQgYSBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbCB0byBleGFtaW5lIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiAqKnN0cmFpZ2h0LWxpbmUgZGlzdGFuY2UgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UqKiAoZXhwb3N1cmUpIGFuZCAqKndlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSB0aW1lKiogKG91dGNvbWUpLCBhZGp1c3RpbmcgZm9yIHBvdGVudGlhbCBjb25mb3VuZGVycyAoc2V4LCBhZ2UsIHNlcykuIAoKYGBge3J9CnN1bW1hcnkobW9kZWxfc3RyYWlnaHQpCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBBIDEwMC1tZXRlciBpbmNyZWFzZSBpbiBzdHJhaWdodC1saW5lIGRpc3RhbmNlIHRvIHRoZSBuZWFyZXN0IGdyZWVuIHNwYWNlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDIuMzctbWludXRlIGRlY3JlYXNlIGluIHdlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzLiBUaGUgbW9kZWwgZXhwbGFpbnMgMy42JSBvZiB0aGUgdmFyaWFuY2UgaW4gd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LiBUaGUgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3IgaW5kaWNhdGVzIGEgc3Vic3RhbnRpYWwgdW5leHBsYWluZWQgdmFyaWFiaWxpdHkgb2YgYXJvdW5kIDMwIG1pbnV0ZXMuIEFsdGhvdWdoIHRoZSBhc3NvY2lhdGlvbiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLCB0aGUgb3ZlcmFsbCBlZmZlY3Qgc2l6ZSBpcyBzbWFsbCwgYW5kIHRoZSBleHBsYW5hdG9yeSBwb3dlciBpcyBsaW1pdGVkLiAKCjwvZGl2PgoKYGBge3J9Cm1vZGVsX25ldHdvcmsgPC0gbG0od2Vla2x5X3BhIH4gbmV0d29ya19kaXN0YW5jZSArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IEluc3RvcmF0aW9uKQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKipuZXR3b3JrIGRpc3RhbmNlIHRvIHRoZSBuZWFyZXN0IGdyZWVuIHNwYWNlKiogKGV4cG9zdXJlKSBhbmQgKip3ZWVrbHkgcGh5c2ljYWwgYWN0aXZpdHkgdGltZSoqIChvdXRjb21lKSwgYWRqdXN0aW5nIGZvciBwb3RlbnRpYWwgY29uZm91bmRlcnMgKHNleCwgYWdlLCBzZXMpLiAKCmBgYHtyfQpzdW1tYXJ5KG1vZGVsX25ldHdvcmspCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPiBBIDEwMC1tZXRlciBpbmNyZWFzZSBpbiBuZXR3b3JrIGRpc3RhbmNlIHRvIHRoZSBuZWFyZXN0IGdyZWVuIHNwYWNlIGlzIGFzc29jaWF0ZWQgd2l0aCBhIDIuMTQtbWludXRlIGRlY3JlYXNlIGluIHdlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzLiBUaGUgbW9kZWwgZXhwbGFpbnMgNC4wJSBvZiB0aGUgdmFyaWFuY2UgaW4gd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LiBUaGUgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3IgaW5kaWNhdGVzIGEgc3Vic3RhbnRpYWwgdW5leHBsYWluZWQgdmFyaWFiaWxpdHkgb2YgYXJvdW5kIDMwIG1pbnV0ZXMuIEFsdGhvdWdoIHRoZSBhc3NvY2lhdGlvbiBpcyBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IChwIDwgMC4wMDEpLCB0aGUgb3ZlcmFsbCBlZmZlY3Qgc2l6ZSBpcyBzbWFsbCwgYW5kIHRoZSBleHBsYW5hdG9yeSBwb3dlciBpcyBsaW1pdGVkLgo8L2Rpdj4KCgpgYGB7cn0KcDEgPC0gZ2dwbG90KEluc3RvcmF0aW9uLCBhZXMoeCA9IHN0cmFpZ2h0X2Rpc3RhbmNlLCB5ID0gd2Vla2x5X3BhKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIGNvbG9yID0gIiNmZjcwYTYiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAiI2ZmMDA1NCIsIGZpbGwgPSAiI0Y3OTZCQiIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiU3RyYWlnaHQtbGluZSB2cy4gUGh5c2ljYWwgQWN0aXZpdHkiLAogICAgeCA9ICJTdHJhaWdodC1saW5lIEdyZWVuIFNwYWNlIChtZXRlcnMpIiwKICAgIHkgPSAiUGh5c2ljYWwgQWN0aXZpdHkgKG1pbnV0ZXMvd2VlaykiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkKYGBgCkNyZWF0ZSBhIHNjYXR0ZXJwbG90IHNob3dpbmcgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gc3RyYWlnaHQtbGluZSBkaXN0YW5jZSB0byB0aGUgY2xvc2VzdCBncmVlbiBzcGFjZSBhbmQgd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LgoKYGBge3J9CnAyIDwtIGdncGxvdChJbnN0b3JhdGlvbiwgYWVzKHggPSBuZXR3b3JrX2Rpc3RhbmNlLCB5ID0gd2Vla2x5X3BhKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjMsIGNvbG9yID0gIiNFNEIwRUUiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgY29sb3IgPSAiI0JFMzlEOCIsIGZpbGwgPSAiI0QzOThERiIpICsKICBsYWJzKAogICAgdGl0bGUgPSAiTmV0d29yayB2cy4gUGh5c2ljYWwgQWN0aXZpdHkiLAogICAgeCA9ICJOZXR3b3JrIEdyZWVuIFNwYWNlIChtZXRlcnMpIiwKICAgIHkgPSAiUGh5c2ljYWwgQWN0aXZpdHkgKG1pbnV0ZXMvd2VlaykiCiAgKSArCiAgdGhlbWVfbWluaW1hbChiYXNlX3NpemUgPSAxMCkKYGBgCkNyZWF0ZSBhIHNjYXR0ZXJwbG90IHNob3dpbmcgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gbmV0d29yayBkaXN0YW5jZSB0byB0aGUgY2xvc2VzdCBncmVlbiBzcGFjZSBhbmQgd2Vla2x5IHBoeXNpY2FsIGFjdGl2aXR5LgoKYGBge3J9CmNvbWJpbmVkX3Bsb3QgPC0gcDEgKyBwMgpjb21iaW5lZF9wbG90CmBgYApDb21iaW5lIHBsb3RzIGZvciBjb21wYXJpc29uIHVzaW5nIHBhdGNod29yay4KCjxkaXYgc3R5bGU9ImNvbG9yOiBncmVlbjsgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgc2VyaWY7IGZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IG5vcm1hbDsiPgogIDxzdHJvbmc+SW50ZXJwcmV0YXRpb248L3N0cm9uZz48YnI+IFdoaWxlIGJvdGggInN0cmFpZ2h0LWxpbmUgZGlzdGFuY2UiIGFuZCAibmV0d29yayBkaXN0YW5jZSIgdG8gdGhlIG5lYXJlc3QgZ3JlZW4gc3BhY2UgYXJlIHNpZ25pZmljYW50bHkgYXNzb2NpYXRlZCB3aXRoIGxvd2VyIHdlZWtseSBwaHlzaWNhbCBhY3Rpdml0eSwgIm5ldHdvcmsgZGlzdGFuY2UiIHNob3dzIGEgc2xpZ2h0bHkgc3Ryb25nZXIgc3RhdGlzdGljYWwgYXNzb2NpYXRpb24gKHQgPSDigJMxNC4xMyB2cy4g4oCTMTMuNTEpIGFuZCBiZXR0ZXIgbW9kZWwgZml0IChSwrIgPSA0LjAlIHZzLiAzLjYlKS4gVGhlc2UgcmVzdWx0cyBzdWdnZXN0IHRoYXQgbmV0d29yayBkaXN0YW5jZSBvZmZlcnMgYSBtb3JlIHJlYWxpc3RpYyBlc3RpbWF0aW9uIG9mIGdyZWVuIHNwYWNlIGFjY2Vzc2liaWxpdHksIGFzIGl0IGlzIGNvbnN0cnVjdGVkIGJhc2VkIG9uIGFjdHVhbCByb3V0ZXMuCjwvZGl2PgoKWyoqRVhFUkNJU0UgNDoqKiBCaW9kaXZlcnNpdHkgcGF0aHdheV17c3R5bGU9ImZvbnQtc2l6ZToyNHB4OyB0ZXh0LWRlY29yYXRpb246dW5kZXJsaW5lO2NvbG9yOmdyZWVuOyJ9CgpUaGlzIGV4ZXJjaXNlIGZvY3VzZXMgb24gdGhlIGJpb2RpdmVyc2l0eSBwYXRod2F5LiBCaW9kaXZlcnNpdHkgaXMgYSBmdW5kYW1lbnRhbCBkZXRlcm1pbmFudCBvZiBoZWFsdGgsIGluZmx1ZW5jaW5nIGJvdGggcGh5c2ljYWwgYW5kIHBzeWNob2xvZ2ljYWwgd2VsbC1iZWluZy4gV2hpbGUgYmlvZGl2ZXJzaXR5IGdlbmVyYWxseSBiZW5lZml0cyBodW1hbiBoZWFsdGgsIGl0IGFsc28gcHJlc2VudHMgYXNzb2NpYXRlZCByaXNrcywgaW5jbHVkaW5nIGV4cG9zdXJlIHRvIGFpcmJvcm5lIGFsbGVyZ2VucyBhbmQgdm9sYXRpbGUgb3JnYW5pYyBjb21wb3VuZHMgdGhhdCBtYXkgdHJpZ2dlciBhbGxlcmdpYyByZWFjdGlvbnMgKE1hcnNlbGxlIGV0IGFsLiwgMjAyMSkuCgoqKkRFU0NSSVBUSU9OKioKCllvdSB3aWxsIGFuYWx5emUgZ2VuZXJhdGVkIGRhdGEgZnJvbSA0LDczMCBwYXJ0aWNpcGFudHMgdG8gZXhhbWluZSBob3cgdmVnZXRhdGlvbiBkaXZlcnNpdHkgaXMgYXNzb2NpYXRlZCB3aXRoIGFsbGVyZ2ljIHJoaW5pdGlzIHN5bXB0b21zIChlLmcuLCBzbmVlemluZywgbmFzYWwgY29uZ2VzdGlvbiwgaXRjaHkgZXllcyksIG1lYXN1cmVkIGFzIHRoZSB0b3RhbCBudW1iZXIgb2YgYW50aWhpc3RhbWluZSBwaWxscyB0YWtlbiBwZXIgeWVhci4gCgpWZWdldGF0aW9uIGRpdmVyc2l0eSBpcyBtb2RlbGVkIGFzIGEgY29udGludW91cyBpbmRleCBiYXNlZCBvbiB0aGUgU2hhbm5vbiBkaXZlcnNpdHkgaW5kZXgsIHdoaWNoIGFjY291bnRzIGZvciBib3RoIGFidW5kYW5jZSBhbmQgZXZlbm5lc3Mgb2YgdGhlIHNwZWNpZXMgcHJlc2VudC4gVGhlIGluZGV4IHJhbmdlcyBmcm9tIDAgKG5vIGRpdmVyc2l0eSkgdG8gYXBwcm94aW1hdGVseSAyLjUgKGhpZ2ggZGl2ZXJzaXR5KSwgd2l0aCBoaWdoZXIgdmFsdWVzIGluZGljYXRpbmcgZ3JlYXRlciBlY29sb2dpY2FsIGRpdmVyc2l0eSBpbiB0aGUgc3Vycm91bmRpbmcgcGxhbnQgZW52aXJvbm1lbnQuCgpgYGB7cn0KbGlicmFyeShyZWFkcikKQmlvZGl2ZXJzaXR5IDwtIHJlYWRfY3N2KCJCaW9kaXZlcnNpdHkuY3N2IikKYGBgCkxvYWQgdGhlIHN5bnRoZXRpYyBkYXRhc2V0IHRpdGxlZCAiQmlvZGl2ZXJzaXR5LmNzdiIuCgpgYGB7cn0Kc3RyKEJpb2RpdmVyc2l0eSkKYGBgCkV4YW1pbmUgdGhlIHN0cnVjdHVyZSBvZiB0aGUgZGF0YXNldC4gVGhlICJCaW9kaXZlcnNpdHkiIGRhdGFzZXQgc2ltdWxhdGVzIGRhdGEgZm9yIDQsNzMwIGFkdWx0IHBhcnRpY2lwYW50cyB3aXRoIHRoZSBmb2xsb3dpbmcgdmFyaWFibGVzOgoKLSAgICoqaWQqKjogSW5kZW50aWZpY2F0aW9uIG51bWJlcgotICAgKip2ZWdfZGl2ZXJzaXR5Kio6IFZlZ2V0YXRpb24gZGl2ZXJzaXR5IGJhc2VkIG9uIHRoZSBTaGFubm9uIGRpdmVyc2l0eSBpbmRleCwgZXN0aW1hdGVkIHdpdGhpbiBhIDMwMC1tZXRlciBidWZmZXIgYXJvdW5kIGVhY2ggcGFydGljaXBhbnTigJlzIHJlc2lkZW5jZS4KLSAgICoqdXJiYW5pY2l0eSoqOiBVcmJhbml6YXRpb24gbGV2ZWwgKFJ1cmFsLCBTdWJ1cmJhbiBvciBVcmJhbikgb2YgdGhlIG5laWdoYm9yaG9vZCBhcmVhLgotICAgKiphbGxlcmd5X21lZCoqOiBUaGUgdG90YWwgbnVtYmVyIG9mIGFudGloaXN0YW1pbmUgcGlsbHMgY29uc3VtZWQgb3ZlciB0aGUgdGhlIHBhc3QgeWVhciwgYXMgYSBwcm94eSBvZiBhbGxlcmdpYyByaGluaXRpcyBzeW1wdG9tIGJ1cmRlbi4KLSAgICoqc2V4Kio6IFNleCAoRmVtYWxlIG9yIE1hbGUpCi0gICAqKmFnZSoqOiBBZ2UgKHllYXJzKQotICAgKipzZXMqKjogU29jaW9lY29ub21pYyBzdGF0dXMgKEkgKGhpZ2hlc3QpIHRvIFYgKGxvd2VzdCkpCgoKYGBge3J9CkJpb2RpdmVyc2l0eSR1cmJhbmljaXR5IDwtIGZhY3RvcihCaW9kaXZlcnNpdHkkdXJiYW5pY2l0eSwgbGFiZWxzID0gYygiUnVyYWwiLCAiU3VidXJiYW4iLCAiVXJiYW4iKSkKQmlvZGl2ZXJzaXR5JHNleCA8LSBmYWN0b3IoQmlvZGl2ZXJzaXR5JHNleCwgbGFiZWxzID0gYygiRmVtYWxlIiwgIk1hbGUiKSkKQmlvZGl2ZXJzaXR5JHNlcyA8LSBmYWN0b3IoQmlvZGl2ZXJzaXR5JHNlcywgbGFiZWxzID0gYygiSSIsICJJSSIsICJJSUkiLCAiSVYiLCAiViIpKQpgYGAKUmVjb2RlIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBpbiB0aGUgIkJpb2RpdmVyc2l0eSIgZGF0YXNldCBhcyBmYWN0b3IuCgpgYGB7cn0KbGlicmFyeShza2ltcikKc2tpbShCaW9kaXZlcnNpdHlbLCBjKCJ2ZWdfZGl2ZXJzaXR5IiwgImFsbGVyZ3lfbWVkIildKQpgYGAKQ2hlY2sgdGhlIGRpc3RyaWJ1dGlvbiBvZiB0aGUgZXhwb3N1cmUgYW5kIG91dGNvbWUgdmFyaWFibGVzLiAKCmBgYHtyfQptb2RlbF9iaW9kaXZlcnNpdHkgPC0gbG0oYWxsZXJneV9tZWQgfiB2ZWdfZGl2ZXJzaXR5ICsgc2V4ICsgYWdlICsgc2VzLCBkYXRhID0gQmlvZGl2ZXJzaXR5KQpgYGAKRml0IGEgbGluZWFyIHJlZ3Jlc3Npb24gbW9kZWwgdG8gZXhhbWluZSB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gKip2ZWdldGF0aW9uIGRpdmVyc2l0eSoqIChleHBvc3VyZSkgYW5kICoqYW50aWhpc3RhbWluZSBwaWxscyBwZXIgeWVhcioqIChvdXRjb21lKSwgYWRqdXN0aW5nIGZvciBwb3RlbnRpYWwgY29uZm91bmRlcnMgKHNleCwgYWdlLCBzZXMpLiAKCmBgYHtyfQpzdW1tYXJ5KG1vZGVsX2Jpb2RpdmVyc2l0eSkKYGBgCjxkaXYgc3R5bGU9ImNvbG9yOiBncmVlbjsgZm9udC1mYW1pbHk6ICdHZW9yZ2lhJywgc2VyaWY7IGZvbnQtc2l6ZTogMTZweDsgZm9udC13ZWlnaHQ6IG5vcm1hbDsiPgogIDxzdHJvbmc+SW50ZXJwcmV0YXRpb248L3N0cm9uZz48YnI+IEEgdW5pdCBpbmNyZWFzZSBpbiB2ZWdldGF0aW9uIGRpdmVyc2l0eSBpcyBhc3NvY2lhdGVkIHdpdGggYW4gZXN0aW1hdGVkIGluY3JlYXNlIG9mIDQuNTIgYW50aWhpc3RhbWluZSBwaWxscyBwZXIgeWVhciwgYWRqdXN0aW5nIGZvciBzZXgsIGFnZSwgYW5kIHNvY2lvZWNvbm9taWMgc3RhdHVzIChwIDwgMC4wMDEpLiBUaGUgbW9kZWwgZXhwbGFpbnMgMTkuMyUgb2YgdGhlIHZhcmlhbmNlIGluIGFudGloaXN0YW1pbmUgdXNlLCB3aXRoIGEgcmVzaWR1YWwgc3RhbmRhcmQgZXJyb3Igb2YgMy40MiBwaWxscywgd2hpY2ggaW5kaWNhdGVzIGEgbW9kZXJhdGUgdW5leHBsYWluZWQgdmFyaWFiaWxpdHkuIAoKPC9kaXY+CgpgYGB7cn0KbGlicmFyeShkcGx5cikKbGlicmFyeShicm9vbSkKCm1vZGVsX2NvZWZmaWNpZW50c191cmJhbmljaXR5IDwtIEJpb2RpdmVyc2l0eSAlPiUKICBncm91cF9ieSh1cmJhbmljaXR5KSAlPiUKICBkbyh0aWR5KGxtKGFsbGVyZ3lfbWVkIH4gdmVnX2RpdmVyc2l0eSArIHNleCArIGFnZSArIHNlcywgZGF0YSA9IC4pKSkgJT4lCiAgZmlsdGVyKHRlcm0gPT0gInZlZ19kaXZlcnNpdHkiKSAgCmBgYApGaXQgdGhlIHByZXZpb3VzIGxpbmVhciByZWdyZXNzaW9uIG1vZGVsLCBidXQgdGhpcyB0aW1lIHN0cmF0aWZpZWQgYnkgKip1cmJhbml6YXRpb24gbGV2ZWwqKi4gVGhpcyBhcHByb2FjaCBhbGxvd3MgdG8gZXhhbWluZSB3aGV0aGVyIHRoZSBzdHJlbmd0aCBvciBkaXJlY3Rpb24gb2YgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gdmVnZXRhdGlvbiBkaXZlcnNpdHkgYW5kIGFsbGVyZ2ljIHJoaW5pdGlzIHN5bXB0b21zIHZhcmllcyBhY3Jvc3MgcnVyYWwsIHN1YnVyYmFuLCBhbmQgdXJiYW4gcmVzaWRlbnRpYWwgY29udGV4dHMuCgoKYGBge3J9CnByaW50KG1vZGVsX2NvZWZmaWNpZW50c191cmJhbmljaXR5KQpgYGAKPGRpdiBzdHlsZT0iY29sb3I6IGdyZWVuOyBmb250LWZhbWlseTogJ0dlb3JnaWEnLCBzZXJpZjsgZm9udC1zaXplOiAxNnB4OyBmb250LXdlaWdodDogbm9ybWFsOyI+CiAgPHN0cm9uZz5JbnRlcnByZXRhdGlvbjwvc3Ryb25nPjxicj4gV2hlbiBzdHJhdGlmaWVkIGJ5IHVyYmFuaXphdGlvbiBsZXZlbCwgdGhlIGFzc29jaWF0aW9uIGJldHdlZW4gdmVnZXRhdGlvbiBkaXZlcnNpdHkgYW5kIGFudGloaXN0YW1pbmUgdXNlIGRpZmZlcnMgaW4gbWFnbml0dWRlLiBJbiB1cmJhbiBhcmVhcywgYSB1bml0IGluY3JlYXNlIGluIHZlZ2V0YXRpb24gZGl2ZXJzaXR5IGlzIGFzc29jaWF0ZWQgd2l0aCBhbiBlc3RpbWF0ZWQgNC40NyBwaWxsIGluY3JlYXNlIHBlciB5ZWFyIChwIDwgMC4wMDEpLCBhZnRlciBhZGp1c3RpbmcgZm9yIHNleCwgYWdlLCBhbmQgc29jaW9lY29ub21pYyBzdGF0dXMuIEluIHN1YnVyYmFuIGFyZWFzLCB0aGUgaW5jcmVhc2UgY29ycmVzcG9uZHMgdG8gMS40MSBwaWxscyBwZXIgeWVhciAocCA8IDAuMDAxKSwgd2hpbGUgaW4gcnVyYWwgYXJlYXMsIHRoZSBhc3NvY2lhdGlvbiBpcyBzbWFsbGVyIGF0IDAuNTYgcGlsbHMgcGVyIHllYXIgKHAgPCAwLjAwMSkuIFRoZXNlIHJlc3VsdHMgc3VnZ2VzdCB0aGF0IHRoZSBoZWFsdGggaW1wYWN0IG9mIHZlZ2V0YXRpb24gZGl2ZXJzaXR5IG1heSBiZSBtb2RpZmllZCBieSB1cmJhbml6YXRpb24gbGV2ZWwuCjwvZGl2PgoKCmBgYHtyfQpnZ3Bsb3QoQmlvZGl2ZXJzaXR5LCBhZXMoeCA9IHZlZ19kaXZlcnNpdHksIHkgPSBhbGxlcmd5X21lZCwgY29sb3IgPSB1cmJhbmljaXR5KSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjQpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBzaXplID0gMS4yKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKAogICAgdmFsdWVzID0gYygiUnVyYWwiID0gIiMwQkRBNTEiLCAiU3VidXJiYW4iID0gIiMxRTkwRkYiLCAiVXJiYW4iID0gIiNGRjM4MDAiKSAgIyB5b3UgY2FuIGNoYW5nZSB0aGVzZQogICkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWZWdldGF0aW9uIERpdmVyc2l0eSB2cy4gQWxsZXJneSBNZWRpY2F0aW9uIiwKICAgIHggPSAiVmVnZXRhdGlvbiBEaXZlcnNpdHkiLAogICAgeSA9ICJBbGxlcmd5IE1lZGljYXRpb24gKHBpbGxzL3llYXIpIiwKICAgIGNvbG9yID0gIlVyYmFuaXphdGlvbiIKICApICsKICB0aGVtZV9taW5pbWFsKCkKCmBgYAo8ZGl2IHN0eWxlPSJjb2xvcjogZ3JlZW47IGZvbnQtZmFtaWx5OiAnR2VvcmdpYScsIHNlcmlmOyBmb250LXNpemU6IDE2cHg7IGZvbnQtd2VpZ2h0OiBub3JtYWw7Ij4KICA8c3Ryb25nPkludGVycHJldGF0aW9uPC9zdHJvbmc+PGJyPgpUaGUgcmVsYXRpb25zaGlwIGJldHdlZW4gdXJiYW5pemF0aW9uIGFuZCBhbGxlcmdpYyBzeW1wdG9tcyAoZS5nLixhc3RobWEsIGFsbGVyZ2ljIHJoaW5pdGlzLCBlY3plbWEsIGZvb2QgYWxsZXJnaWVzKSBoYXMgYmVlbiB3aWRlbHkgc3R1ZGllZCwgYW5kIGVwaWRlbWlvbG9naWNhbCBldmlkZW5jZSBjb25zaXN0ZW50bHkgc2hvd3MgaGlnaGVyIHByZXZhbGVuY2UgYW5kIHNldmVyaXR5IG9mIGFsbGVyZ2ljIGRpc2Vhc2VzIGFtb25nIGluZGl2aWR1YWxzIHJlc2lkaW5nIGluIHVyYmFuIGFyZWFzIHdoZW4gY29tcGFyZWQgdG8gdGhvc2UgdGhhdCByZXNpZGUgaW4gcnVyYWwgc2V0dGluZ3MuVGhpcyBhc3NvY2lhdGlvbiBtYXkgYmUgcGFydGx5IGF0dHJpYnV0ZWQgdG8gcmVkdWNlZCBtaWNyb2JpYWwgZXhwb3N1cmUgaW4gdXJiYW4gZW52aXJvbm1lbnRzLiBVcmJhbml6YXRpb24gaGFzIGJlZW4gYXNzb2NpYXRlZCB0byBsb3dlciBtaWNyb2JpYWwgZGl2ZXJzaXR5LCB3aGljaCBpcyBjb25zaWRlcmVkIGFuIGltcG9ydGFudCBmYWN0b3IgaW4gdGhlIGRldmVsb3BtZW50IG9mIGFsbGVyZ2ljIHNlbnNpdGl6YXRpb24uIEFjY29yZGluZyB0byB0aGUgaHlnaWVuZSBoeXBvdGhlc2lzLCByZWR1Y2VkIGV4cG9zdXJlIHRvIG1pY3JvYmVzIGluIGVhcmx5IGxpZmUgbGltaXRzIGltbXVuZSBzeXN0ZW0gc3RpbXVsYXRpb24sIHBvdGVudGlhbGx5IGluY3JlYXNpbmcgdGhlIHJpc2sgb2YgYWxsZXJnaWMgZGlzZWFzZXMuCgo8L2Rpdj4KCjxkaXYgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPgogIDxoMSBzdHlsZT0iZm9udC1zaXplOiAzMHB4OyBmb250LXdlaWdodDogYm9sZDsgbWFyZ2luLWJvdHRvbTogMDsiPgogICAgRW5kIG9mIHRoZSBhbmFseXNpcyDigJQgVGhhbmsgeW91IGZvciBqb2luaW5nIHRoZSB3b3Jrc2hvcCEKICA8L2gxPgogIAogIAogIAogIAo8L2Rpdj4KCgoK